package cn.jingyuan.swan.system.service.impl;

import cn.jingyuan.bee.utils.StringUtils;
import cn.jingyuan.swan.cloud.core.WarnExceptionUtils;
import cn.jingyuan.swan.system.domain.enums.PersistEnum;
import cn.jingyuan.swan.system.domain.sys.dao.RoleDao;
import cn.jingyuan.swan.system.domain.sys.dao.RoleUserDao;
import cn.jingyuan.swan.system.domain.sys.entity.Role;
import cn.jingyuan.swan.system.domain.sys.entity.RoleUser;
import cn.jingyuan.swan.system.domain.sys.entity.User;
import cn.jingyuan.swan.system.service.RoleService;
import cn.jingyuan.swan.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service
public class RoleServiceImpl implements RoleService {

    @Resource
    RoleDao roleDao;

    @Resource
    RoleUserDao roleUserDao;

    @Resource
    UserService userService;

    @Override
    public Role addRole(Role role) {
        String roleCode = role.getRoleCode();
        if (this.isExist(roleCode)) {
            throw WarnExceptionUtils.newInstance(String.format("角色编码=% 已存在！", role.getRoleCode()));
        }

        if (role.getInvalidStatus() == null) {
            role.setInvalidStatus(true);
        }

        if (role.getIsPersist() == null) {
            role.setIsPersist(PersistEnum.NO);
        }

        Date currentTime = new Date();

        role.setCreateTime(currentTime);
        role.setUpdateTime(currentTime);

        roleDao.insert(role);

        return role;
    }

    @Override
    public void saveUserRoles(Long userId, String... roles) {
        List<String> roleIds = Arrays.asList(roles);
        this.saveUserRoles(userId, roleIds);
    }

    @Override
    public void saveUserRoles(Long userId, Collection<String> roles) {
        if (userId == null || roles == null) {
            return;
        }

        User user = userService.getUser(userId);
        if (null == user) {
            return;
        }

        // 先清空，在添加
        this.removeUserRoles(userId);

        List<RoleUser> sysRoleUsers = new ArrayList<>(roles.size());
        for (String roleId : roles) {
            Date currentTime = new Date();
            RoleUser roleUser = new RoleUser()
                .setUserId(userId)
                .setRoleId(Long.parseLong(roleId))
                .setCreateTime(currentTime)
                .setUpdateTime(currentTime);

            sysRoleUsers.add(roleUser);
        }

        roleUserDao.inserts(sysRoleUsers);
    }

    @Override
    public void saveRoleUsers(Long roleId, Long... userIds) {
        List<Long> ids = Arrays.asList(userIds);
        this.saveRoleUsers(roleId, ids);
    }

    @Override
    public void saveRoleUsers(Long roleId, Collection<Long> userIds) {
        if (roleId == null || userIds == null) {
            return;
        }

        // 先清空,在添加
        this.removeRoleUsers(roleId);

        // 批量保存
        List<RoleUser> sysRoleUsers = new ArrayList<>(userIds.size());
        for (Long userId : userIds) {
            Date currentTime = new Date();
            RoleUser roleUser = new RoleUser()
                .setUserId(userId)
                .setRoleId(roleId)
                .setCreateTime(currentTime)
                .setUpdateTime(currentTime);

            sysRoleUsers.add(roleUser);
        }

        roleUserDao.inserts(sysRoleUsers);
    }

    @Override
    public void removeRole(Long roleId) {
        if (null == roleId) {
            return;
        }

        Role role = this.getRole(roleId);
        if (role != null && role.getIsPersist().equals(1)) {
            throw WarnExceptionUtils.newInstance("保留数据，不允许删除！");
        }

        int row = this.countByRole(roleId);
        if (row > 0) {
            throw WarnExceptionUtils.newInstance("该角色下存在授权人员，不允许删除！");
        }
        // 删除 角色权限
        // FIXME 删除  role 相关资源

        roleDao.delete(roleId);
    }

    @Override
    public void removeRoleUsers(Long roleId) {
        roleUserDao.deleteByRoleId(roleId);
    }

    @Override
    public void removeUserRoles(Long userId) {
        roleUserDao.deleteByUserId(userId);
    }

    @Override
    public Role updateRole(Role role) {
        Role saved = this.getRole(role.getRoleId());
        if (null == saved) {
            throw WarnExceptionUtils.newInstance(String.format("角色不存在，roleId：%s！", role.getRoleId()));
        }

        if (!saved.getRoleCode().equals(role.getRoleCode())) {
            // 和原来不一致重新检查唯一性
            if (this.isExist(role.getRoleCode())) {
                throw WarnExceptionUtils.newInstance(String.format("角色已经存在，角色编码：%s", role.getRoleCode()));
            }
        }
        role.setUpdateTime(new Date());

        roleDao.update(role);

        return role;
    }

    @Override
    public Boolean isExist(String roleCode) {
        if (StringUtils.isBlank(roleCode)) {
            throw WarnExceptionUtils.newInstance("roleCode 不能为空！");
        }

        return roleDao.isExist(roleCode);
    }

    @Override
    public Boolean isExist(Long roleId) {
        return roleDao.isExist(roleId);
    }

    @Override
    public Boolean isExist(Long userId, Long roleId) {
        return roleUserDao.isExist(userId, roleId);
    }

    @Override
    public List<Role> getRole() {
        return roleDao.getAll();
    }

    @Override
    public Role getRole(Long roleId) {
        return roleDao.get(roleId);
    }

    @Override
    public List<Role> findInvalidRoles() {
        // FIXME 修复逻辑
        /*
            1、查询 SysAuthorityRole 中所有出现的不重复路由
            2、查询 SysRole 排查  步骤 1 中的所有路由
         */
        throw new RuntimeException("暂未实现");
    }

    @Override
    public List<RoleUser> findRoleUsers(Long roleId) {
        return roleUserDao.listByRoleId(roleId);
    }

    @Override
    public int countByRole(Long roleId) {
        return roleDao.countByRoleId(roleId);
    }

    @Override
    public int countByUser(Long userId) {
        return roleUserDao.countByUserId(userId);
    }

    @Override
    public List<Role> getUserRoles(Long userId) {
        return null;
    }

    @Override
    public List<Long> getUserRoleIds(Long userId) {
        return null;
    }

}
